using System.Collections.Generic;
using Db4objects.Db4o;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using System.Linq;

namespace testDB
{
    public class UserRepositoryTester
    {
        #region RoleType enum

        public enum RoleType
        {
            User,
            Admin
        }

        #endregion

        #region Nested type: WhenANewUserObjectIsCreated

        [TestFixture]
        public class Given_that_a_user_exist_in_repository:Db4oBaseTester
        {

            protected override void  OnStartup()
            {
 	            repository = new UserRepository(objectContainer);
                user = new User {Username = "testuser", Password = "password"};
                user.Roles = new List<Role> {new Role {RoleType = UserRepositoryTester.RoleType.User}};
                objectContainer.Store(user);
            }

            protected override void OnTearDown()
            {
                objectContainer.Delete(user);
            }

            private IUserRepository repository;
            private User user;


            [Test]
            public void When_a_linq_query_is_exectured_the_user_should_be_returned()
            {

                IEnumerable<User> users = from User u in repository.Query()
                                          where u.Username.Equals("testuser") && u.Roles.Count == 1
                                          select u;

                IList<User> userList = new List<User>(users);

                Assert.That(userList.Count, Is.EqualTo(1));

            }

            [Test]
            public void When_a_user_is_deleted_the_user_should_be_removed_from_the_repository()
            {
                repository.Delete(user);
                
                IObjectSet retrievedUser = objectContainer.QueryByExample(user);
                Assert.That(retrievedUser.Count, Is.EqualTo(0));
            }

            [Test]
            public void When_a_username_is_supplied_the_repository_should_return_the_user()
            {
                User retrivedUser = repository.Get(user.Username);

                Assert.That(user,Is.EqualTo(retrivedUser));
            }

            [Test]
            public void When_the_user_object_is_changed_the_repository_should_save_the_changes()
            {
                user.Username += "1";
                repository.Save(user);

                User retrievedUser = (User) objectContainer.QueryByExample(new User() {Username = user.Username})[0];

                Assert.That(user, Is.EqualTo(retrievedUser));
            }
        }

        #endregion
    }
        
    public abstract class Db4oBaseTester
    {
        protected IObjectContainer objectContainer;

        protected abstract void  OnStartup();
        [SetUp]
        public void Setup()
        {
            objectContainer = PersistanceContainerFactory.Create();
            OnStartup();
        }

        [TearDown]
        public void TearDown()
        {
            OnTearDown();
            objectContainer.Dispose();
            PersistanceContainerFactory.Delete();
        }

        protected abstract void OnTearDown();
    }
}